package tools.csvtools;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.NumberUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
public class ImportCsvUtil {
    /**
     * csv流处理
     *
     * @param inputStream
     * @return
     */
    public static List<idlefishClueInfoDTO> importCsv2Module(InputStream inputStream) {
        List<idlefishClueInfoDTO> idlefishClueInfoDTOS =new ArrayList<>();
        try (InputStreamReader streamReader = new InputStreamReader(inputStream, "GBK");
             BufferedReader textFile = new BufferedReader(streamReader);
        ) {

            String lineDta = null;
            int lineNum = 0;
            while ((lineDta = textFile.readLine()) != null) {
                if (lineNum > 0) {
                    idlefishClueInfoDTO model = processTextLine(lineDta);
                    Optional.ofNullable(processTextLine(lineDta)).ifPresent(idlefishClueInfoDTOS::add);
                }
                lineNum++;
            }

        } catch (IOException e) {
            log.error("csv 流信息导入失败", e);
        }

        return idlefishClueInfoDTOS;
    }

    /**
     * 处理一行的数
     *
     * @param lineData
     * @return
     */
    private static idlefishClueInfoDTO processTextLine(String lineData) {
        String[] fieldNames = getFields(idlefishClueInfoDTO.class);

        idlefishClueInfoDTO chatClueModel = new idlefishClueInfoDTO();
        String[] datas = getDatasFromLine(lineData);
        for (int i = 0; i < datas.length; i++) {
            String val = datas[i];
            String fieldName = fieldNames[i];

            setFieldVal(fieldName, val, chatClueModel);
        }
        return chatClueModel;
    }

    /**
     * 拆解一行的文本数据
     *
     * @param lineData
     * @return
     */
    private static String[] getDatasFromLine(String lineData) {
        int start = 0, end = 0;
        boolean flg = true;
        List<String> words = new ArrayList<>();
        for (int i = 0; i < lineData.length(); i++) {
            char charAt = lineData.charAt(i);
            if (charAt == ',' && flg) {
                words.add(lineData.substring(start, end));
                end++;
                start = end;
            } else if (charAt == '"') {
                if (start == end) {
                    start++;
                    end++;
                    flg = false;
                } else {
                    String word = lineData.substring(start, end);
                    boolean numeric = isNumeric(word.replace(",", ""));
                    if (numeric) {
                        word = word.replace(",", "");
                    }
                    words.add(word);
                    end = end + 2;
                    start = end;
                    i++;
                    flg = true;
                }
            } else {
                end++;
            }
        }
        return words.toArray(new String[words.size()]);
    }

    private static boolean isNumeric(String str) {
        return str != null && str.matches("-?\\d+(\\.\\d+)?");
    }

    private static void setFieldVal(String fieldName, String val, Object target) {
        if (StringUtils.isEmpty(val) || Objects.equals(val, "-")) {
            return;
        }
        Field field = ReflectionUtils.findField(target.getClass(), fieldName);
        ReflectionUtils.makeAccessible(field);

        Class<?> type = field.getType();
        if (type == String.class) {
            ReflectionUtils.setField(field, target, val);
        } else if (type == Long.class) {
            Long aLong = NumberUtils.parseNumber(val, Long.class);
            ReflectionUtils.setField(field, target, aLong);
        } else if (type == Integer.class) {
            Integer aInteger = NumberUtils.parseNumber(val, Integer.class);
            ReflectionUtils.setField(field, target, aInteger);
        }
    }

    private static String[] getFields(Class cls) {
        List<Field> fields = new ArrayList<>();
        ReflectionUtils.doWithFields(cls, field -> {
            ReflectionUtils.makeAccessible(field);
            CsvField annotation = field.getAnnotation(CsvField.class);
            if (annotation != null) {
                fields.add(field);
            }
        });

        List<String> fieldNames = fields.stream().sorted((f1, f2) -> {
            CsvField annotation1 = f1.getAnnotation(CsvField.class);
            CsvField annotation2 = f2.getAnnotation(CsvField.class);
            Comparator<Integer> comparatorInt = Comparator.nullsLast(Comparator.naturalOrder());
            return comparatorInt.compare(annotation1.order(), annotation2.order());
        }).map(Field::getName).collect(Collectors.toList());

        return fieldNames.toArray(new String[fieldNames.size()]);
    }


    public static void main(String[] args) throws IllegalAccessException {
     List<idlefishClueInfoDTO> list = new ArrayList<>();
     List<idlefishClueInfoDTO> list2 = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            list.add(idlefishClueInfoDTO.builder()
                            .acctId(Long.valueOf(i))
                            .acctName(String.valueOf(i))
                    .build());
        }
//        System.out.println(list);

        List<Field> fields = new ArrayList<>();
        ReflectionUtils.doWithFields(idlefishClueInfoDTO.class, field -> {
            ReflectionUtils.makeAccessible(field);
            CsvField annotation = field.getAnnotation(CsvField.class);
            if (annotation != null) {
                fields.add(field);
            }
        });

        for (Object obj : list) {
//            for (Field v : fields) {
//                v.setAccessible(true);
//                Object va = v.get(obj);
//                if (va == null) {
//                    va = "";
//                }
//                System.out.println(va);
//            }

            for (int i = 0; i < fields.size(); i++) {
                System.out.println(fields.get(i).get(obj));
            }
        }
    }
}
